# -*- coding: utf-8 -*-
"""
-------------------------------------------------
Project Name: luffcity study project
File Name: server_view.py
Author: kij
Create Date: 2021/3/18
-------------------------------------------------
"""
import os
import json
import socket
import hashlib
import pymysql
import subprocess
import socketserver
from conf import setting, http_utils
from concurrent.futures import ThreadPoolExecutor


# class MyFtp(socketserver.BaseRequestHandler):
class MyFtp(object):
	"""
	启动服务端
	1、支持多并发
	2、选择多并发类型，io多路复用，io非阻塞，server_socket,线程进程池
	3、登录验证
	4、查看文件
	5、切换路径
	6、登录日志
	7、接收文件
	8、发送文件
	"""

	def cd_dir(self, data_dict, conn_socket=None):
		"""
		跳转文件夹，切换路径,返回切换后的路径
		:return:
		"""

		setting.data_dict.update(data_dict)
		folder_path = os.path.abspath(
			os.path.join(
				setting.USER_HOME_DIR,
				data_dict.get('name'),
				data_dict.get('context_path')[1:],
				data_dict.get('message')[0]))

		if len(folder_path) <= len(os.path.join(setting.USER_HOME_DIR, data_dict.get('name'))):
			setting.data_dict['message'] = '当前文件目录为你的根目录'
			setting.data_dict['context_path'] = '/'

		elif os.path.exists(folder_path):
			setting.data_dict['message'] = "当前文件夹为:%s" % folder_path.replace(
				os.path.join(
					setting.USER_HOME_DIR,
					data_dict.get('name')),
				'')
			setting.data_dict['context_path'] = folder_path.replace(
				os.path.join(setting.USER_HOME_DIR, data_dict.get('name')), '')
		else:
			setting.data_dict['type'] = "error"
			setting.data_dict['message'] = '%s路径不存在' % data_dict.get('message')[0]

		http_utils.send_data(conn_socket, json.dumps(setting.data_dict))

	def ls_dir(self, data_dict, conn_socket=None):
		"""
		根据输入命令，然后返回文件夹进行显示
		:return:
		"""

		setting.data_dict.update(data_dict)
		folder_path = os.path.join(
			setting.USER_HOME_DIR,
			data_dict.get('name'),
			data_dict.get('context_path')[1:]
		)

		cmd_obj = subprocess.Popen(
			"""%s \"%s\"""" % (data_dict.get('type'), folder_path),
			shell=True, stdout=subprocess.PIPE,
			stderr=subprocess.PIPE)

		stdout = cmd_obj.stdout.read()
		stderr = cmd_obj.stderr.read()
		cmd_result = stdout + stderr

		if len(stderr) > 0:
			setting.data_dict['type'] = 'error'
			setting.data_dict['message'] = cmd_result.decode('utf-8')
		else:
			setting.data_dict['message'] = '当前文件夹下内容是:\n%s' % cmd_result.decode('utf-8') if len(
				cmd_result.decode('utf-8')) > 0 else '当前文件夹没内容'

		http_utils.send_data(conn_socket, json.dumps(setting.data_dict))

	def upload(self, data_dict, conn_socket=None):
		"""
		上传文件，上传完成文件返回上传状态信息，是否上传完成
		:return:
		"""
		setting.data_dict.update(data_dict)
		http_utils.send_data(conn_socket, json.dumps(setting.data_dict))
		# 上传文件的当前路径
		file_path = os.path.join(
			setting.USER_HOME_DIR,
			data_dict.get('name'),
			data_dict.get('context_path')[1:],
			data_dict.get('message')[0].rsplit(os.sep, maxsplit=1)[1])
		# 保存客户端发送过来的文件
		http_utils.save_file(conn_socket, file_path)

	def download(self, data_dict, conn_socket=None):
		"""
		下载方法，下载文件，返回下载完成信息
		:return:
		"""
		# 文件的当前路径
		file_path = os.path.join(
			setting.USER_HOME_DIR,
			data_dict.get('name'),
			data_dict.get('context_path')[1:],
			data_dict.get('message')[0])

		setting.data_dict.update(data_dict)
		setting.data_dict['file_name'] = data_dict.get('message')[0].rsplit(os.sep, maxsplit=1)[-1]
		setting.data_dict['file_size'] = os.stat(file_path).st_size
		setting.data_dict['file_path'] = data_dict.get('message')[0]
		http_utils.send_data(conn_socket, json.dumps(setting.data_dict))
		# 给客户端发文件
		http_utils.send_file(conn_socket, file_path)

	def re_get(self, data_dict, conn_socket=None):
		"""
		下载方法，下载文件，返回下载完成信息
		:return:
		"""
		# 文件的当前路径
		file_path = os.path.join(
			setting.USER_HOME_DIR,
			data_dict.get('name'),
			data_dict.get('message')[0])

		setting.data_dict.update(data_dict)

		setting.data_dict['file_name'] = data_dict.get('message')[0].rsplit(os.sep, maxsplit=1)[-1]
		setting.data_dict['file_size'] = os.stat(file_path).st_size
		setting.data_dict['file_path'] = data_dict.get('message')[0]
		setting.data_dict['already_read_size'] = data_dict.get('message')[1]
		# 给客户发送断点续传信息
		http_utils.send_data(conn_socket, json.dumps(setting.data_dict))
		# 继续发送文件
		http_utils.re_send_file(conn_socket, file_path, data_dict.get('message')[1])

	def _mkdir(self, data_dict, conn_socket=None):
		"""
		下载方法，下载文件，返回下载完成信息
		:return:
		"""

		folder_path = os.path.join(
			setting.USER_HOME_DIR,
			data_dict.get('name'),
			data_dict.get('context_path')[1:],
			data_dict.get('message')[0]
		)

		setting.data_dict.update(data_dict)

		if not os.path.exists(folder_path):
			os.makedirs(folder_path)
			setting.data_dict['message'] = '文件夹 %s 创建成功' % data_dict.get('message')[0]
			print(setting.data_dict['message'])
		else:
			setting.data_dict['message'] = '文件已存在'

		http_utils.send_data(conn_socket, json.dumps(setting.data_dict))

	def logon(self, data_dict, conn_socket=None):
		"""
		登录方法，登录成功后拿到根目录路径并显示，还有用户信息
		:return:
		"""
		conn = pymysql.connect(
			host='39.98.160.25',
			port=3306,
			user='kij',
			password='123123',
			db='luffy',
			charset='utf8')

		# 游标
		course = conn.cursor()
		# 执行sql语句

		sql = """select * from ftpuse where username = "%s" and userpassword = "%s";""" % (
			data_dict.get('name'), hashlib.md5(data_dict.get('password').encode('utf-8')).hexdigest())
		print(sql)
		rows = course.execute(sql)
		# for item in range(rows):
		# 	print(course.fetchone())
		# print(course.fetchmany(2))
		print(course.fetchall())
		course.close()
		conn.close()
		print('链接数据库')
		print(rows)
		if rows != 1:
			setting.data_dict.update({
				"type": 'error',
				"message": '账号密码错误',
			})
		else:
			# 发送服务器数据等等待返回结果
			setting.data_dict.update(data_dict)
			folder_path = os.path.join(
				setting.USER_HOME_DIR,
				data_dict.get('name'),
			)
			if not os.path.exists(folder_path):
				os.makedirs(folder_path)
		http_utils.send_data(conn_socket, json.dumps(setting.data_dict))

	def register(self, data_dict, conn_socket=None):
		"""
		登录方法，登录成功后拿到根目录路径并显示，还有用户信息
		:return:
		"""
		# 发送服务器数据等等待返回结果
		# 建立链接
		conn = pymysql.connect(
			host='39.98.160.25',
			port=3306,
			user='kij',
			password='123123',
			db='luffy',
			charset='utf8')

		# 游标
		course = conn.cursor()
		# 执行sql语句
		sql = "INSERT INTO ftpuse (username,userpassword) VALUES (%s,%s);"
		value_data = (data_dict.get('name'), hashlib.md5(data_dict.get('password').encode('utf-8')).hexdigest())
		try:
			# 执行sql语句
			course.execute(sql, value_data)
			# 执行sql语句
			conn.commit()
			setting.data_dict.update(data_dict)
			folder_path = os.path.join(
				setting.USER_HOME_DIR,
				data_dict.get('name'),
			)
			os.makedirs(folder_path)
		except Exception:
			# 发生错误时回滚
			setting.data_dict.update({
				"type": 'error',
				"message": '注册失败',
			})
			conn.rollback()
		course.close()
		conn.close()
		http_utils.send_data(conn_socket, json.dumps(setting.data_dict))

	def client(self, conn):
		try:
			while True:
				res = http_utils.recv_data(conn)
				# 客户端不接收数据后断开
				if not res:
					break
				self.fun_switch(res,conn)
		except Exception as e:
			print(".", e)
			conn.close()

	def fun_switch(self, msg,conn_socket=None):
		msg_dict = json.loads(msg.decode('utf-8'))
		if msg_dict.get('type') not in self.fun_dict:
			http_utils.send_data(conn_socket, json.dumps(
				{
					"type": 'error',
					"message": '服务器没这个方法',
				}))
			setting.data_dict.clear()
		else:
			self.fun_dict.get(msg_dict.get('type'))(self, msg_dict,conn_socket)

	fun_dict = {
		'logon': logon,  # 登录
		'register': register,  # 注册
		'get': download,  # 下载
		'put': upload,  # 上传
		'ls': ls_dir,  # 显示文件加目录
		'dir': ls_dir,  # 显示文件加目录
		'cd': cd_dir,  # 切换文件加目录
		'mkdir': _mkdir,  # 新建文件夹
		're_get': re_get,  # 下载
	}

	# def handle(self):
	# 	self.client(self.request)

	def server(self, pool):
		server = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
		server.setsockopt(socket.SOL_SOCKET, socket.SO_REUSEADDR, 1)
		server.bind(setting.IP_POST)
		server.listen(5)

		while True:
			conn, addr = server.accept()
			print(conn)
			print(addr)
			# p = Process(target=client, args=(conn,))
			# p.start()
			pool.submit(self.client, conn)
		server.close()
